package com.flame.shapeville.service;

import com.flame.shapeville.bean.Course;
import com.flame.shapeville.bean.Exercise;
import com.flame.shapeville.bean.Task;
import com.flame.shapeville.enums.TaskStyle;
import com.flame.shapeville.factory.BeanFactory;
import com.flame.shapeville.util.DbConnector;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Service class responsible for managing tasks in the application.
 * <p>
 * Handles task initialization, loading from database, and associating exercises with each task.
 *
 * @author Flame Dev Team
 * @version 1.0
 * @since 2025-05-04
 */
public class TaskService {
    /**
     * Database connector for Task data.
     */
    private final DbConnector<Task> taskDAO;

    /**
     * Database connector for Course data.
     */
    private final DbConnector<Course> courseDAO;

    /**
     * Constructs a new TaskService instance.
     * Initializes the database connectors for Task and Course.
     */
    public TaskService() {
        taskDAO = new DbConnector<>("db/Task.yml", Task.class);
        courseDAO = new DbConnector<>("db/Course.yml", Course.class);
    }

    /**
     * Loads all tasks associated with a given user and course.
     * If no tasks exist, initializes default tasks and saves them to the database.
     *
     * @param userId   ID of the user whose tasks are being loaded
     * @param courseId ID of the course associated with the tasks
     * @return List of Task objects
     */
    public List<Task> loadTask(String userId, String courseId) {
        Map<String, String> params = Map.of("userId", userId, "courseId", courseId);
        List<Task> tasks = taskDAO.query(params);
        if (tasks.isEmpty()) {
            tasks = initTask(userId, courseId);
            for (Task task : tasks) {
                taskDAO.updateOrSave(task.getId(), task);
            }
        }
        for (Task task : tasks) {
            task.setExercises(loadExercises(task.getId()));
        }
        return tasks;
    }

    /**
     * Loads all tasks for a given user across all courses.
     * If no tasks exist, initializes default tasks for each course and saves them.
     *
     * @param userId ID of the user whose tasks are being loaded
     * @return List of Task objects
     */
    public List<Task> loadTask(String userId) {
        List<Task> tasks = taskDAO.query("userId", userId);
        if (tasks.isEmpty()) {
            List<Course> courses = courseDAO.queryAll();
            for (Course course : courses) {
                String courseId = course.getId();
                tasks = initTask(userId, courseId);
                for (Task task : tasks) {
                    taskDAO.updateOrSave(task.getId(), task);
                }
            }
        }
        for (Task task : tasks) {
            task.setExercises(loadExercises(task.getId()));
        }
        return tasks;
    }

    /**
     * Initializes default tasks based on the course name.
     * - KS1: TASK1, TASK2
     * - KS2: TASK3, TASK4, BONUS1, BONUS2
     *
     * @param userId   ID of the user
     * @param courseId ID of the course
     * @return List of initialized Task objects
     */
    public List<Task> initTask(String userId, String courseId) {
        List<Task> tasks = new ArrayList<>();
        String lastKey = taskDAO.getLastKey();
        if (lastKey == null) {
            lastKey = "0";
        }
        int id = Integer.parseInt(lastKey);

        TaskStyle[] taskStyles = new TaskStyle[]{};
        Course course = courseDAO.querySingleton("id", courseId);
        if (course.getName().equals("KS1")) {
            taskStyles = new TaskStyle[]{TaskStyle.TASK1, TaskStyle.TASK2};
        } else if (course.getName().equals("KS2")) {
            taskStyles = new TaskStyle[]{TaskStyle.TASK3, TaskStyle.TASK4, TaskStyle.BONUS1, TaskStyle.BONUS2};
        }

        for (TaskStyle taskStyle : taskStyles) {
            id++;
            tasks.add(new Task(String.valueOf(id), userId, courseId, taskStyle));
        }
        return tasks;
    }

    /**
     * Loads all exercises associated with a specific task.
     *
     * @param taskId ID of the task
     * @return List of Exercise objects
     */
    public List<Exercise> loadExercises(String taskId) {
        ExerciseService exerciseService = (ExerciseService) BeanFactory.getBean("exerciseService");
        return exerciseService.loadExercise(taskId);
    }
}
